import { Injectable } from "@nestjs/common";
import { Prisma } from "@prisma/client";

import { RequestUser } from "../common/interfaces/request-user.interface";
import { PrismaService } from "../prisma/prisma.service";
import { UserProfileDto } from "./dto/user-profile.dto";

const userWithRoles = Prisma.validator<Prisma.UserInclude>()({
  roles: {
    include: {
      role: true,
    },
  },
});

export type UserWithRoles = Prisma.UserGetPayload<{ include: typeof userWithRoles }>;

@Injectable()
export class UsersService {
  constructor(private readonly prisma: PrismaService) {}

  findById(id: string) {
    return this.prisma.user.findUnique({
      where: { id },
      include: userWithRoles,
    });
  }

  findByIdentifier(identifier: string) {
    const normalized = identifier.trim();
    return this.prisma.user.findFirst({
      where: {
        OR: [
          { email: normalized.toLowerCase() },
          { phone: normalized },
          { employeeCode: normalized },
        ],
      },
      include: userWithRoles,
    });
  }

  async getProfileById(id: string): Promise<UserProfileDto | null> {
    const user = await this.findById(id);
    if (!user) {
      return null;
    }

    return this.toProfileDto(user);
  }

  async updateLastLogin(id: string) {
    await this.prisma.user.update({
      where: { id },
      data: { lastLoginAt: new Date() },
    });
  }

  toRequestUser(user: UserWithRoles): RequestUser {
    return {
      id: user.id,
      email: user.email,
      phone: user.phone,
      displayName: user.displayName,
      roles: user.roles.map((relation) => relation.role.name),
    };
  }

  toProfileDto(user: UserWithRoles): UserProfileDto {
    return {
      id: user.id,
      email: user.email,
      phone: user.phone,
      displayName: user.displayName,
      roles: user.roles.map((relation) => relation.role.name),
      lastLoginAt: user.lastLoginAt,
      createdAt: user.createdAt,
      updatedAt: user.updatedAt,
    };
  }
}
